package cn.xiaopengstack.domain.trade.service.settlement;

import cn.xiaopengstack.domain.trade.adapter.port.ITradePort;
import cn.xiaopengstack.domain.trade.rule.factory.SettlementRuleFilterFactory;
import cn.xiaopengstack.domain.trade.model.aggregate.SettlementOrderAggregate;
import cn.xiaopengstack.domain.trade.model.entity.*;
import cn.xiaopengstack.domain.trade.repository.ITradeRepository;
import cn.xiaopengstack.domain.trade.service.ITradeSettlementOrderService;
import cn.xiaopengstack.types.framework.strategy.link.mutilModel.BusinessLinkedList;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author jiangyangang
 */
@Service
@Slf4j
public class TradeSettlementOrderServiceImpl implements ITradeSettlementOrderService {

    @Resource
    private ITradeRepository tradeRepository;
    @Resource
    private ITradePort tradePort;

    @Resource
    private BusinessLinkedList<SettlementRuleCommandEntity, SettlementRuleFilterFactory.DynamicContext, SettlementRuleResponseEntity> tradeSettlementRuleFilter;

    @Override
    public Map<String, Integer> executeSettlementNotifyJob() {
        List<NotifyTaskEntity> notifyTaskEntities = tradeRepository.queryUnExecutedNotifyTaskList();
        return executeSettlementNotify(notifyTaskEntities);
    }

    @Override
    public Map<String, Integer> executeSettlementNotifyJob(String teamId) {
        List<NotifyTaskEntity> notifyTaskEntities = tradeRepository.queryUnExecutedNotifyTaskList(teamId);
        return executeSettlementNotify(notifyTaskEntities);
    }

    private Map<String, Integer> executeSettlementNotify(List<NotifyTaskEntity> notifyTaskEntities){
        int successCount = 0;
        int errorCount = 0;
        int retryCount = 0;

        for (NotifyTaskEntity notifyTaskEntity : notifyTaskEntities) {

            int notifyResult = tradeRepository.tradeSettlementNotify(notifyTaskEntity);

            if (notifyResult > 0) {
                int updateResult = tradeRepository.updateNotifySuccess(notifyTaskEntity);
                if (updateResult > 0) {
                    successCount++;
                }
            }else {
                if (notifyTaskEntity.getNotifyCount() < 5) {
                    int updateResult = tradeRepository.updateNotifyError(notifyTaskEntity);
                    if (updateResult > 0) {
                        errorCount++;
                    }
                } else {
                    int updateResult = tradeRepository.updateNotifyRetry(notifyTaskEntity);
                    if (updateResult > 0) {
                        retryCount++;
                    }
                }
            }

        }

        HashMap<String, Integer> resultMap = new HashMap<>();
        resultMap.put("totalCount", notifyTaskEntities.size());
        resultMap.put("successCount", successCount);
        resultMap.put("errorCount", errorCount);
        resultMap.put("retryCount", retryCount);
        return resultMap;
    }

    @Override
    public TradePaySettlementEntity settlementOrder(TradePaySuccessEntity tradePaySuccessEntity) throws Exception {
        log.info("拼团订单结算，request={}", JSONObject.toJSONString(tradePaySuccessEntity));

        // 加入责任链
        SettlementRuleResponseEntity responseEntity = tradeSettlementRuleFilter.apply(
                SettlementRuleCommandEntity.builder()
                        .outTradeNo(tradePaySuccessEntity.getOutTradeNo())
                        .userId(tradePaySuccessEntity.getUserId())
                        .channel(tradePaySuccessEntity.getChannel())
                        .source(tradePaySuccessEntity.getSource())
                        .build(),
                new SettlementRuleFilterFactory.DynamicContext()
        );

        // 更新订单详情，新增完成次数
        SettlementOrderAggregate aggregate = SettlementOrderAggregate.builder()
                .userEntity(UserEntity.builder()
                        .userId(tradePaySuccessEntity.getUserId())
                        .build())
                .marketOrderEntity(MarketOrderEntity.builder()
                        .teamId(responseEntity.getTeamId())
                        .orderId(responseEntity.getOrderId())
                        .outOrderNo(tradePaySuccessEntity.getOutTradeNo())
                        .userId(tradePaySuccessEntity.getUserId())
                        .activityId(responseEntity.getActivityId())
                        .build()
                )
                .groupBuyOrderEntity(GroupBuyOrderEntity.builder()
                        .groupEndTime(responseEntity.getGroupEndTime())
                        .groupStartTime(responseEntity.getGroupStartTime())
                        .lockCount(responseEntity.getLockCount())
                        .completeCount(responseEntity.getCompleteCount())
                        .targetCount(responseEntity.getTargetCount())
                        .teamId(responseEntity.getTeamId())
                        .activityId(responseEntity.getActivityId())
                        .build()
                )
                .tradePaySuccessEntity(tradePaySuccessEntity)
                .build();
        tradeRepository.settlementOrder(aggregate);

        return TradePaySettlementEntity.builder()
                .channel(tradePaySuccessEntity.getChannel())
                .source(tradePaySuccessEntity.getSource())
                .outTradeNo(tradePaySuccessEntity.getOutTradeNo())
                .teamId(responseEntity.getTeamId())
                .activityId(responseEntity.getActivityId())
                .build();
    }
}
